Passed
Push — development ( e131c7...d0a4d7 )
by Peter
05:27 queued 13s
created

BicyclesController.createManyBikes   B

Complexity

Conditions 1

Size

Total Lines 72
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

Changes 0
Metric Value
cc 1
eloc 60
dl 0
loc 72
ccs 1
cts 2
cp 0.5
crap 1.125
rs 8.309
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1 2
import {
2
  Controller,
3
  Get,
4
  Post,
5
  Param,
6
  Patch,
7
  Body,
8
  Query,
9
  BadRequestException,
10
} from '@nestjs/common';
11 2
import {
12
  ApiBearerAuth,
13
  ApiOperation,
14
  ApiResponse,
15
  ApiParam,
16
  ApiBody,
17
  ApiTags,
18
  ApiQuery,
19
} from '@nestjs/swagger';
20
// we have removed all JwtAuthGuards from this route.
21
//  import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
22 2
import { BicyclesService } from './bicycles.service';
23 2
import { UpdateBicycleDto } from './dto/update-bicycle.dto';
24
import { Bicycle } from './entities/bicycle.entity';
25
import { BicycleResponse } from './types/bicycle-response.interface';
26 2
import { CreateBicycleDto } from './dto/create-bicycle.dto';
27
28 2
const BIKE_ID = 'b1e77dd3-9fb9-4e6c-a5c6-b6fc58f59464';
29 2
const BIKE_STATUS_AVAILABLE = 'Available';
30 2
const CREATED_AT = '2024-12-01T05:01:01.000Z';
31 2
const UPDATED_AT = '2024-12-07T18:30:30.000Z';
32 2
const UNAUTHORIZED_ERROR_MESSAGE = 'Unauthorized. Authentication required';
33 2
const CITY_ID_GOTHENBURG = '123e4567-e89b-12d3-a456-426614174000';
34
35
@ApiTags('Bicycles')
36
@Controller('bike')
37 2
export class BicyclesController {
38 9
  constructor(private readonly bicyclesService: BicyclesService) {}
39
40
  @Get()
41
  @ApiBearerAuth()
42
  @ApiOperation({ summary: 'Get all bicycles' })
43
  @ApiQuery({
44
    name: 'city',
45
    required: false,
46
    enum: ['Göteborg', 'Jönköping', 'Karlshamn'],
47
  })
48
  @ApiQuery({ name: 'lat', required: false, minimum: -90, maximum: 90 })
49
  @ApiQuery({ name: 'lon', required: false, minimum: -180, maximum: 180 })
50
  @ApiQuery({ name: 'radius', required: false, minimum: 0, maximum: 100000 })
51
  @ApiResponse({
52
    status: 200,
53
    description: 'List of bicycles',
54
    schema: {
55
      type: 'array',
56
      example: [
57
        {
58
          id: BIKE_ID,
59
          batteryLevel: 100,
60
          latitude: 59.3293,
61
          longitude: 18.0686,
62
          status: BIKE_STATUS_AVAILABLE,
63
          city: 'Göteborg',
64
          createdAt: CREATED_AT,
65
          updatedAt: UPDATED_AT,
66
        },
67
      ],
68
    },
69
  })
70
  @ApiResponse({
71
    status: 401,
72
    description: 'Unauthorized. Authentication required',
73
  })
74 2
  async getAllBicycles(
75
    @Query('lat') lat?: string,
76
    @Query('lon') lon?: string,
77
    @Query('radius') radius?: string,
78
    @Query('city') city?: 'Göteborg' | 'Jönköping' | 'Karlshamn',
79
  ): Promise<BicycleResponse[]> {
80 2
    const latitude = lat ? parseFloat(lat) : undefined;
81 2
    const longitude = lon ? parseFloat(lon) : undefined;
82 2
    const radi = radius ? parseFloat(radius) : 3000;
83
84 5
    if ((latitude && !longitude) || (longitude && !latitude)) {
85
      throw new BadRequestException('Both lat and lon must be provided for location search');
86
    }
87
88 2
    if (city) {
89 1
      if (latitude) {
90
        return this.bicyclesService.toBicycleResponses(
91
          await this.bicyclesService.findByCityAndLocation(city, latitude, longitude, radi),
92
        );
93
      }
94
      return this.bicyclesService.toBicycleResponses(await this.bicyclesService.findByCity(city));
95
    }
96
97 2
    if (latitude) {
98
      return this.bicyclesService.toBicycleResponses(
99
        await this.bicyclesService.findByLocation(latitude, longitude, radi),
100
      );
101
    }
102
103 2
    return this.bicyclesService.toBicycleResponses(await this.bicyclesService.findAll());
104
  }
105
106
  @Post('create')
107
  @ApiBearerAuth()
108
  @ApiOperation({ summary: 'Create a new bicycle' })
109
  @ApiBody({
110
    type: CreateBicycleDto,
111
    description: 'Bicycle creation data',
112
    required: false,
113
    schema: {
114
      example: {
115
        batteryLevel: 100,
116
        latitude: null,
117
        longitude: null,
118
        status: BIKE_STATUS_AVAILABLE,
119
        city: 'Göteborg',
120
      },
121
    },
122
  })
123
  @ApiResponse({
124
    status: 201,
125
    description: 'Bicycle created successfully',
126
    schema: {
127
      example: {
128
        id: BIKE_ID,
129
        batteryLevel: 100,
130
        latitude: null,
131
        longitude: null,
132
        status: BIKE_STATUS_AVAILABLE,
133
        city: {
134
          id: CITY_ID_GOTHENBURG,
135
          name: 'Göteborg',
136
          latitude: 57.70887,
137
          longitude: 11.97456,
138
          createdAt: CREATED_AT,
139
          updatedAt: UPDATED_AT,
140
        },
141
        createdAt: CREATED_AT,
142
        updatedAt: UPDATED_AT,
143
      },
144
    },
145
  })
146 2
  async createABike(@Body() createBicycleDto: CreateBicycleDto): Promise<Bicycle> {
147
    console.log('skapa cykel');
148
    return await this.bicyclesService.createBike(createBicycleDto);
149
  }
150
151
  @Post('create-many')
152
  @ApiBearerAuth()
153
  @ApiOperation({ summary: 'Create multiple bicycles' })
154
  @ApiBody({
155
    type: [CreateBicycleDto],
156
    description: 'Array of bicycle creation data',
157
    required: false,
158
    schema: {
159
      example: [
160
        {
161
          batteryLevel: 100,
162
          latitude: null,
163
          longitude: null,
164
          status: BIKE_STATUS_AVAILABLE,
165
          city: 'Göteborg',
166
        },
167
        {
168
          batteryLevel: 100,
169
          latitude: null,
170
          longitude: null,
171
          status: BIKE_STATUS_AVAILABLE,
172
          city: 'Göteborg',
173
        },
174
      ],
175
    },
176
  })
177
  @ApiResponse({
178
    status: 201,
179
    description: 'Bicycles created successfully',
180
    schema: {
181
      type: 'array',
182
      example: [
183
        {
184
          id: BIKE_ID,
185
          batteryLevel: 100,
186
          latitude: null,
187
          longitude: null,
188
          status: BIKE_STATUS_AVAILABLE,
189
          city: {
190
            id: CITY_ID_GOTHENBURG,
191
            name: 'Göteborg',
192
            latitude: 57.70887,
193
            longitude: 11.97456,
194
            createdAt: CREATED_AT,
195
            updatedAt: UPDATED_AT,
196
          },
197
          createdAt: CREATED_AT,
198
          updatedAt: UPDATED_AT,
199
        },
200
        {
201
          id: BIKE_ID,
202
          batteryLevel: 100,
203
          latitude: null,
204
          longitude: null,
205
          status: BIKE_STATUS_AVAILABLE,
206
          city: {
207
            id: CITY_ID_GOTHENBURG,
208
            name: 'Göteborg',
209
            latitude: 57.70887,
210
            longitude: 11.97456,
211
            createdAt: CREATED_AT,
212
            updatedAt: UPDATED_AT,
213
          },
214
          createdAt: CREATED_AT,
215
          updatedAt: UPDATED_AT,
216
        },
217
      ],
218
    },
219
  })
220 2
  async createManyBikes(@Body() createBicycleDto: CreateBicycleDto[]): Promise<Bicycle[]> {
221
    return await this.bicyclesService.createManyBikes(createBicycleDto);
222
  }
223
224
  @Get(':bikeId')
225
  @ApiBearerAuth()
226
  @ApiOperation({ summary: 'Get a bicycle by ID' })
227
  @ApiParam({
228
    name: 'bikeId',
229
    description: 'Unique identifier of the bicycle',
230
    type: 'string',
231
    example: BIKE_ID,
232
  })
233
  @ApiResponse({
234
    status: 200,
235
    description: 'Bicycle details retrieved successfully',
236
    schema: {
237
      example: {
238
        id: BIKE_ID,
239
        batteryLevel: 100,
240
        latitude: 59.3293,
241
        longitude: 18.0686,
242
        status: BIKE_STATUS_AVAILABLE,
243
        city: 'Göteborg',
244
        createdAt: CREATED_AT,
245
        updatedAt: UPDATED_AT,
246
      },
247
    },
248
  })
249
  @ApiResponse({
250
    status: 401,
251
    description: UNAUTHORIZED_ERROR_MESSAGE,
252
  })
253
  @ApiResponse({
254
    status: 404,
255
    description: 'Bicycle not found',
256
  })
257 2
  async getBikeById(@Param('bikeId') id: string): Promise<Bicycle> {
258 2
    return await this.bicyclesService.findById(id);
259
  }
260
261
  @Patch(':bikeId')
262
  @ApiBearerAuth()
263
  @ApiOperation({ summary: 'Update bicycle by ID' })
264
  @ApiParam({
265
    name: 'bikeId',
266
    description: 'Unique identifier of the bicycle',
267
    type: 'string',
268
    example: BIKE_ID,
269
  })
270
  @ApiBody({
271
    description: 'Bicycle update details',
272
    type: UpdateBicycleDto,
273
  })
274
  @ApiResponse({
275
    status: 200,
276
    description: 'Bicycle updated successfully',
277
    schema: {
278
      example: {
279
        id: BIKE_ID,
280
        batteryLevel: 85,
281
        latitude: 59.3294,
282
        longitude: 18.0687,
283
        status: 'Service',
284
        city: 'Göteborg',
285
      },
286
    },
287
  })
288
  @ApiResponse({
289
    status: 400,
290
    description: 'Invalid input',
291
  })
292
  @ApiResponse({
293
    status: 404,
294
    description: 'Bicycle not found',
295
  })
296
  @ApiResponse({
297
    status: 401,
298
    description: UNAUTHORIZED_ERROR_MESSAGE,
299
  })
300 2
  async updateBicycle(@Param('bikeId') bikeId: string, @Body() updateBicycleDto: UpdateBicycleDto) {
301 3
    return this.bicyclesService.update(bikeId, updateBicycleDto);
302
  }
303
304
  @Get('city/:cityName')
305
  @ApiBearerAuth()
306
  @ApiOperation({ summary: 'Get all bicycles in a specific city' })
307
  @ApiResponse({
308
    status: 200,
309
    description: 'List of bicycles in the specified city',
310
    schema: {
311
      type: 'array',
312
      example: [
313
        {
314
          id: BIKE_ID,
315
          batteryLevel: 80,
316
          latitude: 59.8586,
317
          longitude: 17.6389,
318
          status: 'Rented',
319
          createdAt: CREATED_AT,
320
          updatedAt: UPDATED_AT,
321
          city: {
322
            id: 'd2322ff3-a81c-4b06-b78d-1bc72b4fe459',
323
            name: 'Karlshamn',
324
            latitude: null,
325
            longitude: null,
326
            createdAt: CREATED_AT,
327
            updatedAt: UPDATED_AT,
328
          },
329
        },
330
      ],
331
    },
332
  })
333
  @ApiResponse({
334
    status: 401,
335
    description: UNAUTHORIZED_ERROR_MESSAGE,
336
  })
337
  @ApiParam({
338
    name: 'cityName',
339
    description: 'Name of the city',
340
    type: 'string',
341
    enum: ['Göteborg', 'Jönköping', 'Karlshamn'],
342
  })
343 2
  async getBicyclesByCity(@Param('cityName') cityName: 'Göteborg' | 'Jönköping' | 'Karlshamn') {
344
    return await this.bicyclesService.findByCity(cityName);
345
  }
346
}
347